#!/usr/bin/env python
# -*- coding: utf-8 -*-

import re
import os
from typing import Dict, List
from ruamel import yaml
from common.setting import ensure_path_sep


class MarkdownToYaml:
    """Markdown 接口文档转 YAML 测试用例"""

    def __init__(self, md_file_path: str):
        self.md_file_path = md_file_path
        self.content = self._read_markdown()
        self.interfaces = self._parse_interfaces()

    def _read_markdown(self) -> str:
        """读取 Markdown 文件内容"""
        try:
            with open(self.md_file_path, 'r', encoding='utf-8') as f:
                return f.read()
        except FileNotFoundError:
            raise FileNotFoundError(f"文件 {self.md_file_path} 不存在")

    def _parse_interfaces(self) -> List[Dict]:
        """解析 Markdown 中的接口信息"""
        interfaces = []

        # 匹配接口标题 (如 #### 发送邮箱验证码)
        pattern_title = r'####\s*(.+?)\n'
        titles = re.findall(pattern_title, self.content)

        # 分割每个接口块
        interface_blocks = re.split(pattern_title, self.content)[1:]

        for i in range(0, len(interface_blocks), 2):
            if i + 1 < len(interface_blocks):
                title = interface_blocks[i].strip()
                block_content = interface_blocks[i + 1]

                interface_info = {
                    'title': title,
                    'url': self._extract_url(block_content),
                    'method': self._extract_method(block_content),
                    'description': self._extract_description(block_content),
                    'headers': self._extract_headers(block_content),
                    'parameters': self._extract_parameters(block_content),
                    'responses': self._extract_responses(block_content)
                }
                interfaces.append(interface_info)

        return interfaces

    def _extract_url(self, content: str) -> str:
        """提取 URL"""
        # 适配您的文档格式 "接口URL" 和环境表格
        url_match = re.search(r'接口URL.*?>\s*([^\s\n]+)', content, re.IGNORECASE)
        if url_match:
            return url_match.group(1)
        # 备用方案：查找任何类似URL的内容
        url_match = re.search(r'https?://[^\s\n]+', content)
        return url_match.group(0) if url_match else "/default/path"

    def _extract_method(self, content: str) -> str:
        """提取请求方法"""
        method_match = re.search(r'请求方式.*?>\s*(\w+)', content, re.IGNORECASE)
        return method_match.group(1).upper() if method_match else "GET"

    def _extract_parameters(self, content: str) -> Dict:
        """提取请求参数"""
        params = {}
        # 查找参数表格
        params_match = re.search(r'请求Body参数[\s\S]*?(\|.*?\|.*?\|.*?\|.*?\|.*?\|[\s\S]*?)(?=\n\w|\Z)', content,
                                 re.IGNORECASE)
        if params_match:
            params_content = params_match.group(1)
            # 匹配表格格式的参数
            param_matches = re.findall(
                r'\|\s*([^|\n]+?)\s*\|\s*([^|\n]+?)\s*\|\s*([^|\n]+?)\s*\|\s*([^|\n]+?)\s*\|\s*([^|\n]+?)\s*\|',
                params_content)
            if len(param_matches) > 1:  # 有表头
                for param in param_matches[1:]:  # 跳过表头
                    params[param[0].strip()] = None
        return params

    def _extract_url(self, content: str) -> str:
        """提取 URL"""
        # 适配您的文档格式 "接口URL" 和环境表格
        url_match = re.search(r'接口URL.*?>\s*([^\s\n>]+)', content, re.IGNORECASE)
        if url_match:
            url = url_match.group(1)
            # 清理 URL 中的非法字符
            return re.sub(r'[<>:"|?*]', '', url).strip()
        # 备用方案：查找任何类似URL的内容
        url_match = re.search(r'https?://[^\s\n>]+', content)
        if url_match:
            return url_match.group(0)
        return "/default/path"
    def _extract_method(self, content: str) -> str:
        """提取请求方法"""
        method_match = re.search(r'[`\*]*(GET|POST|PUT|DELETE|PATCH)[`\*]*', content, re.IGNORECASE)
        return method_match.group(1).upper() if method_match else "GET"

    def _extract_description(self, content: str) -> str:
        """提取接口描述"""
        # 提取第一行非标题的文本作为描述
        lines = content.strip().split('\n')
        for line in lines:
            if line.strip() and not re.match(r'^[#`*\-\d]+', line):
                return line.strip()
        return "接口测试"

    def _extract_headers(self, content: str) -> Dict:
        """提取请求头"""
        headers = {}
        headers_match = re.search(r'[`\*]*Headers[`\*]*[:：]?([\s\S]*?)(?=\n##|\Z)', content, re.IGNORECASE)
        if headers_match:
            headers_content = headers_match.group(1)
            header_lines = re.findall(r'(\w+-?\w*):\s*([^\n]+)', headers_content)
            headers = {k.strip(): v.strip() for k, v in header_lines}
        return headers or {"Content-Type": "application/json"}

    def _extract_parameters(self, content: str) -> Dict:
        """提取请求参数"""
        params = {}
        # 查找参数表格或列表
        params_match = re.search(r'[`\*]*Parameters[`\*]*[:：]?([\s\S]*?)(?=\n##|\Z)', content, re.IGNORECASE)
        if params_match:
            params_content = params_match.group(1)
            # 匹配表格格式的参数
            param_matches = re.findall(r'\|\s*([^|\n]+?)\s*\|\s*([^|\n]+?)\s*\|\s*([^|\n]+?)\s*\|', params_content)
            if len(param_matches) > 1:  # 有表头
                for param in param_matches[1:]:  # 跳过表头
                    params[param[0].strip()] = None
            else:
                # 匹配列表格式的参数
                list_params = re.findall(r'-\s*([^:\n]+?):', params_content)
                for param in list_params:
                    params[param.strip()] = None
        return params

    def _extract_responses(self, content: str) -> Dict:
        """提取响应示例"""
        responses = {}
        resp_match = re.search(r'[`\*]*Response[`\*]*[:：]?([\s\S]*?)(?=\n##|\Z)', content, re.IGNORECASE)
        if resp_match:
            try:
                import json
                resp_content = resp_match.group(1)
                # 尝试解析 JSON 响应示例
                json_match = re.search(r'', resp_content, re.DOTALL)
                if json_match:
                    responses = json.loads(json_match.group(1))
            except:
                pass
        return responses

    def get_allure_epic(self, interface_info: Dict) -> str:
        """获取 allure epic"""
        return "接口测试"

    def get_allure_feature(self, interface_info: Dict) -> str:
        """获取 allure feature"""
        return interface_info['title']

    def get_allure_story(self, interface_info: Dict) -> str:
        """获取 allure story"""
        return interface_info['description']

    def get_case_id(self, url: str, index: int) -> str:
        """生成 case_id"""
        clean_url = re.sub(r'[^\w]', '_', url)
        return f"case_{index:02d}_{clean_url}"

    def get_detail(self, interface_info: Dict) -> str:
        """获取测试用例详情"""
        return f"测试 {interface_info['title']} - {interface_info['description']}"

    def get_request_type(self, interface_info: Dict) -> str:
        """确定请求类型"""
        method = interface_info['method']
        headers = interface_info['headers']

        if method == 'GET':
            return 'params'
        elif 'application/json' in str(headers):
            return 'json'
        elif 'application/x-www-form-urlencoded' in str(headers):
            return 'data'
        else:
            return 'json'  # 默认

    def get_case_data(self, interface_info: Dict) -> Dict:
        """获取测试数据"""
        return interface_info['parameters'] or None

    def get_headers(self, interface_info: Dict) -> Dict:
        """获取请求头"""
        return interface_info['headers'] or {"Content-Type": "application/json"}

    def yaml_cases(self, data: Dict, file_path: str) -> None:
        """写入 YAML 数据"""
        _file_path = ensure_path_sep("\\data\\" + file_path.lstrip("/").replace("/", os.sep) + '.yaml')
        _file = _file_path.split(os.sep)[:-1]
        _dir_path = ''
        for i in _file:
            _dir_path += i + os.sep
        try:
            os.makedirs(_dir_path)
        except FileExistsError:
            pass

        with open(_file_path, "w", encoding="utf-8") as file:
            yaml.dump(data, file, Dumper=yaml.RoundTripDumper, allow_unicode=True)
            file.write('\n')

    # 在 generate_yaml_cases 方法中添加路径清理
    def generate_yaml_cases(self):
        """生成所有 YAML 测试用例"""
        for index, interface in enumerate(self.interfaces, 1):
            url = interface['url']
            # 清理 URL 中的非法字符用于文件路径
            clean_url = re.sub(r'[^\w\-/.]', '_', url)
            yaml_data = {
                "case_common": {
                    "allureEpic": self.get_allure_epic(interface),
                    "allureFeature": self.get_allure_feature(interface),
                    "allureStory": self.get_allure_story(interface)
                },
                self.get_case_id(url, index): {
                    "host": "${{host()}}",
                    "url": url,
                    "method": interface['method'],
                    "detail": self.get_detail(interface),
                    "headers": self.get_headers(interface),
                    "requestType": self.get_request_type(interface),
                    "is_run": True,
                    "data": self.get_case_data(interface),
                    "dependence_case": False,
                    "assert": {
                        "status_code": 200
                    },
                    "sql": None
                }
            }

            # 使用清理后的 URL 作为文件路径
            file_path = clean_url.replace("/{version}", "").replace("/{api}", "")
            self.yaml_cases(yaml_data, file_path)


if __name__ == '__main__':
    # 使用示例
    md_to_yaml = MarkdownToYaml("C:/Users/Lenovo/Desktop/Mooligirl-V2.0.md")
    md_to_yaml.generate_yaml_cases()
    print("YAML 测试用例生成完成")
